package com.chorye.datasource.common.utils;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.*;

/**
 * @Company: 北京XXXX有限公司
 * @Author JiangYy
 * @Title: CodeGeneratorUtil
 * @Description: MP代码生成工具类
 * @Date 2018/12/13 10:12
 */
public class CodeGeneratorUtil {

    /**
     * 代码生成
     *
     * @param args
     */
    public static void main(String[] args) {
        // 生成代码
        generateCode();
    }

    /**
     * 生成代码的具体逻辑
     */
    private static void generateCode() {
        // 用来获取mybatis-plus.properties文件的配置信息
        final ResourceBundle config = ResourceBundle.getBundle("mybatis-plus-generator");

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        /**
         * 1、全局配置
         */
        GlobalConfig gc = new GlobalConfig();
        // 是否开启ActiveRecord模式
        gc.setActiveRecord(Boolean.valueOf(config.getString("openActiveRecord")))
                // 作者
                .setAuthor(config.getString("author"))
                // 生成后不打开文件夹
                .setOpen(false)
                // 输出的路径
                .setOutputDir(config.getString("outputDir"))
                // 是否覆盖上一次生成
                .setFileOverride(true)
                // 主键策略
//                .setIdType(IdType.NONE)
                // 设置实体类名称
                .setEntityName("%s")
                // 设置接口类名称
                .setMapperName("%sMapper")
                // 设置xml名称
                .setXmlName("%sMapper")
                // 设置生成的service接口的名字的首字母是否为I
                .setServiceName("%sService")
                // 设置service实现类名称
//                .setServiceImplName("%sServiceImpl")
                // 设置controller名称
                .setControllerName("%sController")
                // 设置生成的主键类型
//                .setIdType(IdType.AUTO)
                // 是否开启swagger
//                .setSwagger2(true)
                // 是否生成xml中的BaseResultMap映射
                .setBaseResultMap(true)
                // 是否生成xml中的BaseColumn
                .setBaseColumnList(true);
        // 设置进代码生成器
        mpg.setGlobalConfig(gc);

        /**
         * 2、数据源配置
         */
        DataSourceConfig dsc = new DataSourceConfig();
        // 数据库类型为mysql
        dsc.setDbType(DbType.MYSQL)
                // 驱动
                .setDriverName(config.getString("driverName"))
                // url
                .setUrl(config.getString("url"))
                // 数据库用户名
                .setUsername(config.getString("username"))
                // 数据库密码
                .setPassword(config.getString("password"));
        // 设置进代码生成器
        mpg.setDataSource(dsc);

        /**
         * 3、包配置
         */
        PackageConfig pc = new PackageConfig();
        // 设置父包
        pc.setParent(config.getString("parent"))
                // 设置模块名
//                .setModuleName("ta")
                // 设置接口类位置，xml文件位置此处不做定义，后面自定义位置
                .setMapper(config.getString("mapperLocation"))
                // 设置service位置
                .setService(config.getString("serviceLocation"))
                // 设置service实现类位置
//                .setServiceImpl("impl")
                // 设置controller位置
                .setController(config.getString("controllerLocation"))
                // 设置实体类位置
                .setEntity(config.getString("entityLocation"));
        // 设置进代码生成器
        mpg.setPackageInfo(pc);

        /**
         * 3、注入自定义模板配置
         */
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                this.setMap(map);
            }
        };
        // 自定义配置
        // 调整 xml 生成目录，放在resources下
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mybatisTpl/mapper.xml.vm") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return config.getString("outputDirXml") + tableInfo.getEntityName() + "Mapper.xml";
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 自定义模板配置，可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改，
        TemplateConfig tc = new TemplateConfig();
        // 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置，也可以自定义模板名称
        if (Boolean.valueOf(config.getString("generateController"))) {
            tc.setController("/templates/mybatisTpl/controller.java.vm");
        } else {
            tc.setController(null);
        }
        tc.setEntity("/templates/mybatisTpl/entity.java.vm");
        tc.setService("/templates/mybatisTpl/service.java.vm");
        // 关闭默认 xml 生成，调整生成 至 resources
        tc.setXml(null);
        // 不使用 service--serviceImpl模式，直接使用service作为实现类，所以不生成实现类，使用自定义的service模板
        tc.setServiceImpl(null);
        // 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
        mpg.setTemplate(tc);

        /**
         * 4、策略配置
         */
        StrategyConfig strategy = new StrategyConfig();
        // 表前缀解析
        String[] tablePrefix = config.getString("tablePrefix").split(",");
        // 表解析
        String[] include = config.getString("tables").split(",");
        // 是否大写命名
        strategy.setCapitalMode(false)
                // 设置表前缀
                .setTablePrefix(tablePrefix)
                // 设置要生成表
                .setInclude(include)
                // 根据表名生成实体类名的策略
                .setNaming(NamingStrategy.underline_to_camel)
                // 字段名生成实体类字段名的策略
//                .setColumnNaming(NamingStrategy.nochange)
                // 生成 @RestController 控制器
                .setRestControllerStyle(true)
                // 生成实体类注释
                .entityTableFieldAnnotationEnable(true);
        // 设置进代码生成器
        mpg.setStrategy(strategy);

        /**
         * 5、执行生成
         */
        mpg.execute();
    }
}
